package com.hmy.contract.service.contract.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmy.ccp.starter.web.utils.UserContextUtil;
import com.hmy.contract.bo.request.contractProcess.ContractProcessApprovalRequest;
import com.hmy.contract.bo.request.contractProcess.ContractProcessRejectRequest;
import com.hmy.contract.bo.request.contractProcess.ContractProcessStartRequest;
import com.hmy.contract.bo.response.contractProcess.ContractProcessApprovalResponse;
import com.hmy.contract.bo.response.contractProcess.ContractProcessRejectResponse;
import com.hmy.contract.bo.response.contractProcess.ContractProcessStartResponse;
import com.hmy.contract.commons.enums.ContractStatusEnum;
import com.hmy.contract.dal.mapper.ContractProcessMapper;
import com.hmy.contract.dal.po.ContractPo;
import com.hmy.contract.dal.po.ContractProcessPo;
import com.hmy.contract.manager.entry.EntryFormFeignClientManager;
import com.hmy.contract.manager.exit.ExitFormFeignClientManager;
import com.hmy.contract.manager.order.OrderFeignClientManager;
import com.hmy.contract.manager.signature.SignatureFeignClientManager;
import com.hmy.contract.manager.worklfow.FlowTaskClientManager;
import com.hmy.contract.service.contract.IContractProcessService;
import com.hmy.contract.service.contract.IContractService;
import com.hmy.contract.service.dto.contractProcess.ContractProcessApprovalDto;
import com.hmy.contract.service.oss.IOssService;
import com.hmy.order.api.bo.request.ContractOrderStatusUpdateApiRequest;
import com.hmy.order.api.common.enums.OrderStatusEnum;
import com.hmy.workflow.api.bo.request.task.ApprovalTaskRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 合同信息表 服务实现类
 *
 * @author seven.qi
 * @since 2023-12-02
 */
@Service
@Slf4j
public class ContractProcessServiceImpl extends ServiceImpl<ContractProcessMapper, ContractProcessPo> implements IContractProcessService {

    @Resource
    private OrderFeignClientManager orderFeignClientManager;

    @Resource
    private IContractService contractService;

    @Resource
    private FlowTaskClientManager flowTaskClientManager;

    @Resource
    private SignatureFeignClientManager signatureFeignClientManager;

    @Resource
    private IOssService ossService;

    @Resource
    private EntryFormFeignClientManager entryFormFeignClientManager;

    @Resource
    private ExitFormFeignClientManager exitFormFeignClientManager;

    @Override
    public ContractProcessStartResponse startProcess(ContractProcessStartRequest contractProcessStartRequest) {
        ContractProcessPo contractProcessPo = new ContractProcessPo();
        BeanUtil.copyProperties(contractProcessStartRequest, contractProcessPo);
        UserContextUtil.initCreatorInfo(contractProcessPo);
        UserContextUtil.initUpdaterInfo(contractProcessPo);
        save(contractProcessPo);
        return null;
    }

    @Override
    @Transactional
    public ContractProcessApprovalResponse approval(ContractProcessApprovalRequest contractProcessApprovalRequest) {
        ContractPo contractPo = contractService.getById(contractProcessApprovalRequest);
        contractPo.setStatus(ContractStatusEnum.APPROVED.getStatus());
        contractService.updateById(contractPo);

        ContractProcessApprovalDto dto = new ContractProcessApprovalDto();
        BeanUtil.copyProperties(contractProcessApprovalRequest, dto);

        try {
            completeTask(dto);
        } catch (Exception e) {
            log.error("completeTask exception", e);
        }

        try {
            notifyOrderStatus(contractPo.getContractNo(), contractPo.getOrderId(), OrderStatusEnum.PASS_EXAMINE.getOrderStatusCode());
        } catch (Exception e) {
            log.error("notifyOrder exception", e);
        }

        ContractProcessApprovalResponse contractProcessApprovalResponse = new ContractProcessApprovalResponse();
        contractProcessApprovalResponse.setContractId(contractPo.getContractId());
        return contractProcessApprovalResponse;
    }

    private void completeTask(ContractProcessApprovalDto dto) {
        ApprovalTaskRequest approvalTaskRequest = new ApprovalTaskRequest();
        approvalTaskRequest.setProcessInstanceId(dto.getProcessId().toString());
        approvalTaskRequest.setTaskId(dto.getTaskId().toString());
        //approvalTaskRequest.setUserId(UserContextUtil.getCurrentUserId());
        approvalTaskRequest.setComment(dto.getComment());
        Map<String, Object> params = new HashMap<>();
        params.put("command", dto.getVariables().get("command"));
        approvalTaskRequest.setVariables(params);
        flowTaskClientManager.complete(approvalTaskRequest);
    }

    @Override
    @Transactional
    public ContractProcessRejectResponse reject(ContractProcessRejectRequest contractProcessRejectRequest) {
        ContractPo contractPo = contractService.getById(contractProcessRejectRequest);
        contractPo.setStatus(ContractStatusEnum.REJECT.getStatus());
        contractService.updateById(contractPo);

        ContractProcessApprovalDto dto = new ContractProcessApprovalDto();
        BeanUtil.copyProperties(contractProcessRejectRequest, dto);

        try {
            completeTask(dto);
        } catch (Exception e) {
            log.error("completeTask exception", e);
        }

        try {
            notifyOrderStatus(contractPo.getContractNo(), contractPo.getOrderId(), OrderStatusEnum.REFUSE_EXAMINE.getOrderStatusCode());
        } catch (Exception e) {
            log.error("notifyOrder exception", e);
        }

        ContractProcessRejectResponse contractProcessRejectResponse = new ContractProcessRejectResponse();
        contractProcessRejectResponse.setContractId(contractPo.getContractId());
        return contractProcessRejectResponse;
    }

    private void notifyOrderStatus(String contractId, Long orderId, Byte status) {
        orderFeignClientManager.updateContractOrderStatus(new ContractOrderStatusUpdateApiRequest(orderId, status));
    }
}
